package com.stone.boot.file.app.service.impl;

import cn.hutool.json.JSONUtil;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.stone.boot.file.app.service.OssService;
import com.stone.boot.file.domain.bo.OssCallbackParam;
import com.stone.boot.file.domain.bo.OssCallbackResult;
import com.stone.boot.file.domain.bo.OssPolicyResult;
import com.stone.boot.file.infra.util.FileUploadUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * oss上传管理Service实现类
 *
 * @author Mr_wenpan@163.com 2021/8/19 2:48 下午
 */
@Service
public class OssServiceImpl implements OssService {
    private static final Logger LOGGER = LoggerFactory.getLogger(OssServiceImpl.class);
    @Value("${aliyun.oss.policy.expire}")
    private int aliyunOssExpire;
    @Value(("${aliyun.oss.maxSize}"))
    private int aliyunOssMaxSize;
    @Value("${aliyun.oss.callback}")
    private String aliyunOssCallback;
    @Value("${aliyun.oss.bucketName}")
    private String aliyunOssBucketName;
    @Value("${aliyun.oss.endpoint}")
    private String aliyunOssEndpoint;
    @Value("${aliyun.oss.dir.prefix}")
    private String aliyunOssDirPrefix;

    @Autowired
    private OSSClient ossClient;

    /**
     * 签名生成
     */
    @Override
    public OssPolicyResult policy() {
        OssPolicyResult ossPolicyResult = new OssPolicyResult();
        // 存储目录
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String dir = aliyunOssDirPrefix + sdf.format(new Date());
        // 签名有效期
        long expireEndTime = System.currentTimeMillis() + aliyunOssExpire * 1000;
        Date expiration = new Date(expireEndTime);
        // 文件大小
        int maxSize = aliyunOssMaxSize * 1024 * 1024;
        // 回调
        OssCallbackParam ossCallbackParam = new OssCallbackParam();
        ossCallbackParam.setCallbackUrl(aliyunOssCallback);
        ossCallbackParam.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
        ossCallbackParam.setCallbackBodyType("application/x-www-form-urlencoded");
        // 提交节点
        String action = "http://" + aliyunOssEndpoint;
        try {
            PolicyConditions policyConditions = new PolicyConditions();
            policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize);
            policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConditions);
            byte[] binaryData;
            binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String policy = BinaryUtil.toBase64String(binaryData);
            String signature = ossClient.calculatePostSignature(postPolicy);
            String callbackData = BinaryUtil.toBase64String(JSONUtil.parse(ossCallbackParam).toString().getBytes(StandardCharsets.UTF_8));
            // 返回结果
            ossPolicyResult.setAccessKeyId(ossClient.getCredentialsProvider().getCredentials().getAccessKeyId());
            ossPolicyResult.setPolicy(policy);
            ossPolicyResult.setSignature(signature);
            ossPolicyResult.setDir(dir);
            ossPolicyResult.setCallback(callbackData);
            ossPolicyResult.setHost(action);
        } catch (Exception e) {
            LOGGER.error("签名生成失败", e);
        }
        return ossPolicyResult;
    }

    @Override
    public OssCallbackResult callback(HttpServletRequest request) {
        OssCallbackResult ossCallbackResult = new OssCallbackResult();
        String filename = request.getParameter("filename");
        filename = "http://".concat(aliyunOssBucketName).concat(".").concat(aliyunOssEndpoint).concat("/").concat(filename);
        ossCallbackResult.setFilename(filename);
        ossCallbackResult.setSize(request.getParameter("size"));
        ossCallbackResult.setMimeType(request.getParameter("mimeType"));
        ossCallbackResult.setWidth(request.getParameter("width"));
        ossCallbackResult.setHeight(request.getParameter("height"));
        return ossCallbackResult;
    }

    @Resource
    private FileUploadUtil fileUploadUtil;

    @Override
    public Map<String, Object> upload(MultipartFile file, String fileName) {
        // 定义一个目录（这里的目录可根据自己实际情况自己拼接定义）
        // 我这里就随便定义一个a文件夹
        final String path = "a";
        // 拼接，这里将路径和文件名拼接在了一起
        fileName = path + "/" + fileName;
        Map<String, Object> map = new HashMap<>();
        map.put("code", 200);
        map.put("msg", "查询成功");
        map.put("data", fileUploadUtil.upload(file, fileName));
        return map;
    }

}